🐣 VanillaJS 둜 SPA κ΅¬ν˜„ν•˜μž! ν›„κΈ°

@Hyunho Jang Β· January 19, 2023 Β· 6 min read

ν”„λ‘ νŠΈ 기술 μ—­λŸ‰μ„ κ°•ν™”ν•˜κΈ° μœ„ν•΄ JavaScript 기반 SPA ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€. μš”λ²ˆ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ λ¦¬μ—‘νŠΈ, λ·°μ—μ„œ μ‚¬μš©ν•˜λŠ” μ›ΉνŒ©, λΌμš°ν„° λ“±μ˜ 기술이 μ™œ μ‚¬μš©ν•˜λŠ”μ§€, μ–΄λ–€ μ›λ¦¬λ‘œ λ™μž‘λ˜λŠ”μ§€ λ°°μ›Œλ³Ό 수 μžˆμ—ˆλ˜ κ²½ν—˜μ΄μ˜€κ³  라이브러리λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  순수 μžλ°”μŠ€ν¬λ¦½νŠΈλ§Œμ„ μ΄μš©ν•΄ μ—¬λŸ¬ λ‘œμ§μ„ κ³ λ―Όν•˜λ©° μ›Ήκ°œλ°œμžλ‘œμ„œ ν•œμΈ΅ μ„±μž₯ν•  수 μžˆλŠ” κΈ°νšŒμ˜€λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

κΈ€μ˜ μˆœμ„œλŠ” 크게 μ•„λž˜μ™€ 같이 μ§„ν–‰ν•˜κ² μŠ΅λ‹ˆλ‹€.

  1. SPA κ°œλ°œμ— μ‚¬μš©ν•œ 기술 μ†Œκ°œ
  2. μ£Όμš” 둜직

SPA? μžλ°”μŠ€ν¬λ¦½νŠΈλ§ŒμœΌλ‘œ μ–΄λ–»κ²Œ κ°œλ°œν•˜μ§€

κ·Έλ™μ•ˆ ν”„λ‘ νŠΈ κ°œλ°œμ„ ν•΄μ˜€λ©΄μ„œ λ¦¬μ—‘νŠΈ, λ·° 라이브러리λ₯Ό μ΄μš©ν•΄ 아무 생각 없이 μ½”λ“œλ₯Ό μ§œλ‹€λ³΄λ‹ˆ, μ •μž‘ SPA 기술이 μ–΄λ–»κ²Œ λ™μž‘λ˜λŠ”μ§€ λͺ¨λ₯΄λŠ” κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μƒν™©μ—μ„œ κ°‘μžκΈ° μžλ°”μŠ€ν¬λ¦½νŠΈλ§ŒμœΌλ‘œ 개발이 주어진 경우 λ§‰μ—°νžˆ μ–΄λ ΅κ²Œλ§Œ λ‹€κ°€μ™”μŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μ§„μ§œ 라이브러리 도움없이 순수 μžλ°”μŠ€ν¬λ¦½νŠΈλ§Œμ„ μ΄μš©ν•œ κ°œλ°œμ„ μ‹œλ„ν–ˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ μ„ νƒν•œ 방법이 hash(Hash History) 방식!

μžλ°”μŠ€ν¬λ¦½νŠΈλ§ŒμœΌλ‘œ SPA κ°œλ°œν•˜λŠ” 방식은 크게 2가지가 μžˆμŠ΅λ‹ˆλ‹€. ν•˜λ‚˜λŠ” history(Browser History), λ˜ν•˜λ‚˜λŠ” hash λ₯Ό μ΄μš©ν•΄ SPAλ₯Ό κ΅¬ν˜„ν•  μˆ˜κ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œ μ €λŠ” hash 방식을 μ„ νƒν•΄μ„œ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

κ·Έ μ΄μœ λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈλ§ŒμœΌλ‘œ 정적 μ›Ήμ„œλ²„μ— 배포λ₯Ό 해보고 μ‹Άμ—ˆκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. history 방식은 express μ„œλ²„ ꡬ좕이 ν•„μš”ν–ˆκΈ°μ— μ €λŠ” μ„œλ²„ ꡬ좕이 ν•„μš”μ—†λŠ” hash 방식을 μ„ νƒν–ˆμŠ΅λ‹ˆλ‹€.

hash μ‚¬μš©ν•΄ SPA κ°œλ°œν•΄λ³΄μž

크게 λ‘œμ§μ€ μ•„λž˜μ™€ 같은 ꡬ쑰둜 μ§„ν–‰λ˜κ²Œ λ©λ‹ˆλ‹€. μ—¬κΈ°μ„œ hash λŠ” User μš”μ²­μ˜ λ„μž…λΆ€λΆ„μΈ λΌμš°ν„°μ— μœ„μΉ˜ν•˜κ²Œ λ©λ‹ˆλ‹€.

SPA ꡬ쑰
SPA ꡬ쑰

μš”μ²­μ˜ 첫 μ‹œμž‘μ€ Navigation

μ—¬κΈ°μ„œ hash 의 역할이 κΆκΈˆν• κ»λ‹ˆλ‹€. hashλŠ” # 액컀λ₯Ό 톡해 μ΄λ™ν•˜λŠ” λ°©λ²•μœΌλ‘œ site/#path 와 같이 url이 ν‘œν˜„λ©λ‹ˆλ‹€. 보톡 정적 νŽ˜μ΄μ§€μ—μ„œ μ‚¬μš©λ˜λ©° λΈ”λ‘œκ·Έμ˜ μ£Ό 제λͺ©μ„ 클릭 ν›„ 액컀 이동 μ‹œ url에 #이 λΆ™λŠ” λͺ¨μŠ΅μ„ 보싀 수 μžˆμŠ΅λ‹ˆλ‹€.

 window.addEventListener("hashchange", () => {
        router(window.location.hash);
    })
const router = (route) => {
    rootContent.innerHTML = '';
    switch (route) {
        case '#/':
            return rootContent.appendChild(pages.home());
        case '#/detail':
            return rootContent.appendChild(pages.detail());
        case '#/post':
            return rootContent.appendChild(pages.post());
        default:
            return rootContent.appendChild(pages.notFound());
    }
}

window.location.hash μ΄μš©ν•΄ λΌμš°νŒ… 변경이 되며 μ΄λŠ” hash λ³€κ²½ μ‹œ hashchange μ΄λ²€νŠΈκ°€ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— λΌμš°νŒ…μ΄ κ°€λŠ₯ν•΄μ§‘λ‹ˆλ‹€.

Controller μ›ν•˜λŠ” νŽ˜μ΄μ§€ μƒμ„±λ˜κ²Œλ” ν•΄μ£Όμž

ν•΄λ‹Ή hash에 λ§žλŠ” 경둜둜 이동 μ‹œ νŽ˜μ΄μ§€λ₯Ό λ³΄μ—¬μ£ΌλŠ” λ°©λ²•μž…λ‹ˆλ‹€. μœ„μ˜ ꡬ쑰와 같이 λΌμš°νŒ…μ„ 거쳐 μ»¨νŠΈλ‘€λŸ¬μ— μš”μ²­μ΄ λ“€μ–΄κ°€μ§€κ²Œ λ©λ‹ˆλ‹€. λ‹€μŒμœΌλ‘œ μš”μ²­μ— λ§žλŠ” νŽ˜μ΄μ§€ 생성을 μœ„ν•œ μ„œλΉ„μŠ€ 둜직이 μ‹€ν–‰λ˜κ²Œ λ©λ‹ˆλ‹€.

// μ„€λͺ…을 μœ„ν•œ μ΅œμ†Œν•œμ˜ μ½”λ“œμž…λ‹ˆλ‹€. ν•΄λ‹Ή μ½”λ“œμ— μ‹€μ œ axiosλ₯Ό μ΄μš©ν•œ 데이터 처리 λ‘œμ§λ„ λ‹΄κ²Œλ©λ‹ˆλ‹€.
import views from '../views/post/post.html'

export default () => {
    const divElement = document.createElement('div')
    divElement.classList = "post-section";
    divElement.innerHTML = views;

    return divElement;
}

μ½”λ“œμ— 보싀 수 μžˆλ“―μ΄ ν•΄λ‹Ή μ—˜λ ˆλ¨ΌνŠΈλ₯Ό 생성 ν›„ μ•ˆμ—λ‹€ 미리 μƒμ„±λœ html λ·°λ₯Ό μ§‘μ–΄λ„£λŠ” λ°©μ‹μœΌλ‘œ νŽ˜μ΄μ§€ ꡐ체가 μ§„ν–‰λ˜κ²Œ λ©λ‹ˆλ‹€.

μΆ”κ°€λ‘œ history(browser hisotry) λŠ”?

url ν˜•νƒœλŠ” site/path 와 같이 ν‘œν˜„λ˜λ©° 이 방법은 μ„œλ²„ μΈ‘ 지원이 일뢀 ν•„μš”ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경둜둜 접속할 경우 였λ₯˜λ₯Ό 좜λ ₯ν•˜λ©° 이런 문제λ₯Ό ν•΄κ²°ν•˜κ³  λŒ€μ²΄ν•  url은 μ„œλ²„μ— 지정해야 λ©λ‹ˆλ‹€.

history API의 pushstate popstate 이벀트λ₯Ό μ΄μš©ν•©λ‹ˆλ‹€. history.pushstate 톡해 μƒˆ 데이터 전달을 μœ„ν•œ μƒνƒœ, 제λͺ©, url 지정이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

λŠλ‚€μ 

κ·Έλ™μ•ˆ ν”„λ ˆμž„μ›Œν¬, 라이브러리의 λ™μž‘μ„ μ„€λͺ…을 보고 λ‹¨μˆœνžˆ κΈ°λŠ₯ λ™μž‘ν•˜λŠ” 개발만 ν–ˆμ—ˆλŠ”λ° μ‹€μ œ 이미 κ΅¬ν˜„λœ κΈ°λŠ₯을 μ²˜μŒλΆ€ν„° κ°œλ°œμ„ ν•΄λ³΄λ©΄μ„œ κΈ°λŠ₯의 원리λ₯Ό 쒀더 이해할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 그리고 짧은 μ‹œκ°„ λ‚΄ κ°œλ°œμ„ μ§„ν–‰ν•˜λ©° ν…ŒμŠ€νŠΈ 및 μ‚¬μš©μžμ˜ 휴먼 μ—λŸ¬λ₯Ό 많이 κ³ λ €ν•˜μ§€ μ•Šκ³  μžˆλ‹€λŠ” λΆ€λΆ„μ—μ„œ μ•„μ‰¬μ› μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μš”λ²ˆ ν”„λ‘œμ νŠΈλ₯Ό 톡해 개인적인 개발 μ„±μž₯을 λ‹¬μ„±ν–ˆλ‹€λŠ” μ μ—μ„œ μž¬λ°Œμ—ˆλ˜ ν”„λ‘œμ νŠΈμ˜€λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

μ½”λ“œκ°€ κΆκΈˆν•˜μ‹œλ‹€λ©΄?
GitHub

@Hyunho Jang
ν”„λ‘œμ νŠΈ 기술 λΈ”λ‘œκ·Έμž…λ‹ˆλ‹€.